package org.lifxue.jqda.ui.autofield;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 
 * @Description:
 * @Author: zhangzuoqiang
 * @Date: Sep 26, 2011
 */
public class AutoCompletionField extends JTextField implements
		DocumentListener, MouseListener, ListSelectionListener, ActionListener,
		KeyListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private static Log logger = LogFactory.getLog(AutoCompletionField.class);

	private static int DEFAULT_PREFERRED_HEIGHT = 200;
	private ListPopup popup;
	private int preferredHeight = DEFAULT_PREFERRED_HEIGHT;
	private CompletionFilter filter;

	public void setFilter(CompletionFilter f) {
		filter = f;
	}

	public AutoCompletionField() {
		popup = new ListPopup();
		getDocument().addDocumentListener(this);
		addMouseListener(this);
		popup.addListSelectionListener(this);
		addActionListener(this);
		addKeyListener(this);
	}

	public void setPopupPreferredHeight(int h) {
		preferredHeight = h;
	}

	private boolean isListChange(ArrayList<?> array) {
		if (array.size() != popup.getItemCount()) {
			return true;
		}
		for (int i = 0; i < array.size(); i++) {
			if (!array.get(i).equals(popup.getItem(i))) {
				return true;
			}
		}
		return false;
	}

	private void textChanged() {
		if ("".equals(this.getText())) {
			popup.setVisible(false);
		} else {
			if (!popup.isVisible()) {
				showPopup();
				// requestFocus();
				requestFocusInWindow();
			}
			if (filter != null) {
				ArrayList<?> array = filter.filter(getText());
				changeList(array);
			}
		}
	}

	private void showPopup() {
		popup.setPopupSize(getWidth(), preferredHeight);
		popup.show(this, 0, getHeight() - 1);

	}

	private void changeList(ArrayList<?> array) {
		if (array.isEmpty()) {
			if (popup.isVisible()) {
				popup.setVisible(false);
			}
		} else {
			if (!popup.isVisible()) {
				showPopup();
			}
		}
		if (isListChange(array) && !array.isEmpty()) {
			popup.setList(array);
			popup.setSelectedIndex(0);
		}
	}

	@Override
	public void insertUpdate(DocumentEvent e) {
		logger.debug("insertUpdate");
		textChanged();
	}

	@Override
	public void removeUpdate(DocumentEvent e) {
		logger.debug("removeUpdate");
		textChanged();
	}

	@Override
	public void changedUpdate(DocumentEvent e) {
		logger.debug("changedUpdate");
		textChanged();
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		logger.debug("mouseClicked");
		if (e.getClickCount() > 1 && !popup.isVisible()) {
			textChanged();
		}
	}

	@Override
	public void mousePressed(MouseEvent e) {
	}

	@Override
	public void mouseReleased(MouseEvent e) {
	}

	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}

	/**
	 * JList的鼠标单击监听 在下拉列表上鼠标单击一列数据，激活此监听
	 * 
	 * @param e
	 */
	@Override
	public void valueChanged(ListSelectionEvent e) {
		JList list = (JList) e.getSource();
		String text = list.getSelectedValue().toString();
		logger.debug(text);
		setText(text);
		popup.setVisible(false);
	}

	/**
	 * 回车键监听
	 * 
	 * @param e
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
	}

	@Override
	public void keyTyped(KeyEvent e) {
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_DOWN) {
			if (popup.isVisible()) {
				if (!popup.isSelected()) {
					popup.setSelectedIndex(0);
				} else {
					popup.setSelectedIndex(popup.getSelectedIndex() + 1);
				}
			}
		} else if (e.getKeyCode() == KeyEvent.VK_UP) {
			if (popup.isVisible()) {
				if (!popup.isSelected()) {
					popup.setLastOneSelected();
				} else {
					popup.setSelectedIndex(popup.getSelectedIndex() - 1);
				}
			}
		} else if (e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) {
			if (popup.isVisible()) {
				if (!popup.isSelected()) {
					popup.setSelectedIndex(0);
				} else {
					popup.setSelectedIndex(popup.getSelectedIndex() + 5);
				}
			}
		} else if (e.getKeyCode() == KeyEvent.VK_PAGE_UP) {
			if (popup.isVisible()) {
				if (!popup.isSelected()) {
					popup.setLastOneSelected();
				} else {
					popup.setSelectedIndex(popup.getSelectedIndex() - 5);
				}
			}
		} else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
			if (popup.isVisible()) {
				Object o = popup.getSelectedValue();
				if (o != null) {
					setText(o.toString());
					logger.debug(o.toString());
				}
				popup.setVisible(false);
			}
			this.selectAll();
			this.requestFocus();

		}
	}

	@Override
	public void keyReleased(KeyEvent e) {
	}
}
